home *** CD-ROM | disk | FTP | other *** search
Oberon Text | 1990-11-07 | 47.9 KB | 983 lines | [.Ob./.Ob*] |
- Syntax16.Scn.Fnt
- Syntax12.Scn.Fnt
- Syntax12i.Scn.Fnt
- Syntax14.Scn.Fnt
- Syntax10.Scn.Fnt
- Syntax12b.Scn.Fnt
- Guide for Programmers of Commands
- In Oberon's modular hierarchy we recognize the following structural entities: The inner core, the outer core,
- the text system, the graphic system, the picture system, and a collection of tools.
- Oberon's module hierarchy
- Tool Packages
- Net Backup Compiler System Miscellaneous ColorSystem
- Edit Draw Paint
- Text System Graphic System Picture System
- TextFrames GraphicFrames PictureFrames
- Graphics Pictures
- MenuViewers
- Outer Core
- Inner Core Printer Oberon
- Texts
- Modules Fonts
- Files
- FileDir Math MathL Reals Viewers
- Drivers Kernel V24 SCC Diskette Input Display
-
- The responsability of the inner core comprises memory management, file management, and program
- loading. The outer core additionally provides device drivers for network ports, keyboard, mouse, and display
- screens. Other parts of the outer core are viewer manager, elementary text management, and support for
- (remote) printing. Module Oberon represents the main interface between the outer core and its clients. It
- includes sections that are devoted to the current system configuration, to default strategies for track
- allocation and viewer placement, and to the support of command execution.
- Module Display stands at the bottom of the display system hierarchy. The display area is considered as a
- plane with x and y coordinates. It includes both a black-and-white area and a color area. Raster operations
- are used to generate and copy rectangular areas on the display plane. Sections of the plane can be made
- visible by display control procedures. The visible parts of the display plane are structured as tracks and
- viewers, and they are managed by the viewer manager Viewers. Module Oberon defines a standard layout
- featuring one user track and one system track per display screen. Finally, module MenuViewers is a
- high-level viewer manager for standard viewers consisting of a title bar and a rectangular main area
- surrounded by a thin frame. Both title bar and main area are so-called frames. While the title bar is almost
- always a text frame (see next paragraph), the type of the main frame depends on the kind of viewer.
- The text system, the graphic system, and the picture system are identical in structure. Each consists of a triple
- of linearly dependent modules. In the case of texts they are called Texts, TextFrames, and Edit. Texts defines
- the object type Text and exports intrinsic operations on texts. TextFrames defines the object type
- TextFrames.Frame and handles representations of texts within sub-frames of viewers. Edit provides
- additional (non-built-in) text-editing operations.
- Modules at the top (like Edit) are tool packages. Typically, a tool package merely exports a collection of
- commands in the form of parameterless procedures. Tool modules make intensive use of facilities provided
- by lower level modules, in particular by the viewer system, the text system, and the central system module
- Oberon. It is essential that usual commands strictly operate on texts or graphics instead of accessing
- keyboard or screen directly.
- We understand this chapter as a tutorial on implementing tool packages. First, we give a commented
- overview of the definitions of the most important lower-level modules. Then, we shall exemplify their
- usage by some typical excerpts from existing tools.
- The Display System
- DEFINITION Display; (*display driver*)
- CONST black = 0; white = 15;
- replace = 0; paint = 1; invert = 2; (*operation modes*)
- TYPE
- Frame = POINTER TO FrameDesc;
- FrameMsg = RECORD END; (*base type of messages to frames*)
- Pattern = LONGINT; (*pointer to pattern descriptor*)
- (*PatternDesc = RECORD
- w, h: SHORTINT;
- raster: ARRAY (w + 7) DIV 8 * h OF BYTE
- END*)
- Font = POINTER TO Bytes;
- Bytes = RECORD END;
- Handler = PROCEDURE (Frame, VAR FrameMsg);
- FrameDesc = RECORD (*base type of frames*)
- dsc, next: Frame;
- X, Y, W, H: INTEGER;
- handle: Handler
- END;
- VAR
- Unit: LONGINT; (*RasterUnit = Unit/36000 mm*)
- Left, (*left margin of black-and-white maps*)
- ColLeft, (*left margin of color maps*)
- Bottom, (*Bottom of primary map*)
- UBottom, (*Bottom of secondary map*)
- Width, (*map width*)
- Height: (*map height*)
- INTEGER;
- arrow, star, cross, downArrow, hook: Pattern;
- PROCEDURE Map (X: INTEGER): LONGINT; (*address of map at X*)
- PROCEDURE SetMode (X: INTEGER; s: SET); (*set mode of map at X*)
- (*black & white display: 0: display disable, 1: display secondary map, 2: inverse video*)
- (*color display*)
- PROCEDURE SetColor (col, red, green, blue: INTEGER); (*col < 0: overlay color*)
- PROCEDURE GetColor (col: INTEGER; VAR red, green, blue: INTEGER);
- PROCEDURE SetCursor(mode: SET); (*color cursor; 0: crosshair, 1: arrow*)
- PROCEDURE InitCC; (*initialize color crosshair to full screen*)
- PROCEDURE InitCP; (*initialize color pattern to arrow shape*)
- PROCEDURE DefCC (X, Y, W, H: INTEGER); (*define window for color crosshair*)
- PROCEDURE DefCP (VAR raster: ARRAY OF BYTE); (*define 64 x 64 raster for color pattern marker*)
- PROCEDURE DrawCX (X, Y: INTEGER); (*draw color cursor at X, Y*)
- PROCEDURE FadeCX (X, Y: INTEGER); (*fade color cursor at X, Y*)
- (*fonts*)
- PROCEDURE GetChar(f: Font; ch: CHAR; VAR dx, x, y, w, h: INTEGER; VAR p: Pattern);
- (*get box x, y, w, h, width dx, and raster data p of character ch in font f*)
- (*raster operations*)
- PROCEDURE CopyBlock (SX, SY, W, H, DX, DY, mode: INTEGER);
- (*copy source block SX, SY, W, H to destination DX, DY using operation mode.
- A block is given by its lower left corner X, Y and its dimension W, H*)
- PROCEDURE CopyPattern (col: INTEGER; pat: Pattern; X, Y, mode: INTEGER);
- (*copy pattern p in color col to X, Y using operation mode
- col = 0: black; col = 15: white*)
- PROCEDURE ReplPattern (col: INTEGER; pat: Pattern; X, Y, W, H, mode: INTEGER);
- (*replicate pattern p in color col into block X, Y, W, H using operation mode,
- proceeding from left to right and from bottom to top, starting at lower left corner*)
- PROCEDURE ReplConst (col: INTEGER; X, Y, W, H, mode: INTEGER);
- (*place "ones" in color col into block X, Y, W, H using operation mode*)
- END Display.
- Remarks:
- 1. The Ceres computer features a monochrome display whose position (lower left corner) is specified by the
- variables Left and Bottom, and whose width and height are given by the variables Width and Height. In fact,
- the drawing area is bigger; its y-coordinate ranges from -1248 to 799. Two sections can be made visible by
- the display control procedures, the first being characterized by {y| -1024 <= y < -224}, and the other by {y| 0
- <= y < 800}.
- 2. If a color display is installed, the module's raster procedures can be used to generate and copy areas on the
- color screen. The position of the color area (lower left corner) is specified by the variables ColLeft and
- Bottom; its width and height are the same as for the monochrome display.
- 3. The postulated preconditions upon procedure parameters are not checked by the module; this is left to
- the calling modules which are held responsible for robustness.
- 4. Notice that there are the following implementation restrictions of the raster operations:
- ReplConst
- Color display: paint mode treated as replace mode. of this module
- ReplPattern
- Pattern width w ignored and taken as 32 on monochrome and as 16 on color
- display. 0 <= h < 256 on monochrome, 0 <= h <= 16 on color display.
- Color display: x and x+w should be even, otherwise 1 is subtracted.
- CopyPattern
- Replace mode treated like paint mode.
- 0 < w <= 32, 0 <= h < 256.
- CopyBlock
- All modes treated as replace mode.
- ------------------------------------------------------------------------
- DEFINITION Viewers; (*viewer manager*)
- IMPORT Display;
- CONST
- restore = 0; modify = 1; suspend = 2;
- (*message ids referring to the following message type*)
- TYPE
- Message = RECORD (*message sent to viewers on viewer events*)
- (Display.FrameMsg)
- id: INTEGER;
- X, Y, W, H: INTEGER;
- state: INTEGER
- END;
- Viewer = POINTER TO ViewerDesc;
- ViewerDesc = RECORD (*viewer descriptor extends Display.FrameDesc*)
- (Display.FrameDesc)
- state: INTEGER
- END;
- (*state > 1: displayed
- state = 1: filler
- state = 0: closed
- state < 0: suspended*)
- VAR curW, minH: INTEGER; (*current width of logical display, minimum viewer height*)
- PROCEDURE InitTrack (W, H: INTEGER; Filler: Viewer);
- (*append to current logical display and init track of width W and height H and install Filler*)
- PROCEDURE OpenTrack (X, W: INTEGER; Filler: Viewer);
- (*open new track overlaying span of [X, X + W[*)
- PROCEDURE CloseTrack (X: INTEGER);
- (*close track at X and restore overlaid tracks*)
- PROCEDURE Locate (X, H: INTEGER; VAR fil, bot, alt, max: Display.Frame);
- (*in the track at X locate the following viewers:
- filler fil,
- bottom viewer bot,
- an alternative viewer alt of height >= H,
- viewer max of maximum height*)
- PROCEDURE Open (V: Viewer; X, Y: INTEGER);
- (*open new viewer V with top at Y in track at X*)
- PROCEDURE Change (V: Viewer; Y: INTEGER);
- (*expand or shrink viewer V to new top Y*)
- PROCEDURE Close (V: Viewer);
- (*remove viewer V from the display*)
- PROCEDURE Recall (VAR V: Viewer);
- (*recall most recently closed viewer*)
- PROCEDURE This (X, Y: INTEGER): Viewer;
- (*return viewer at X, Y*)
- PROCEDURE Next (V: Viewer): Viewer;
- (*return next upper neighbour of V*)
- PROCEDURE Broadcast (VAR M: Display.FrameMsg);
- (*send message M to all visible viewers*)
- END Viewers.
- --------------------------------------------------------------------------
- DEFINITION MenuViewers;
- IMPORT Display, Viewers;
- CONST extend = 0; reduce = 1; (*message ids*)
- TYPE
- Viewer = POINTER TO ViewerDesc;
- ViewerDesc = RECORD (Viewers.ViewerDesc)
- menuH: INTEGER (*height of menu frame*)
- END;
- ModifyMsg = RECORD (Display.FrameMsg)
- id: INTEGER; (*extend or reduce*)
- dY, Y, H: INTEGER (*translation vector dY; new Y and H*)
- END;
- VAR Ancestor: Viewer; (*current menu viewer*)
- PROCEDURE Handle (V: Display.Frame; VAR M: Display.FrameMsg);
- (*standard handler for menu viewers*)
- PROCEDURE New (Menu, Main: Display.Frame; menuH, X, Y: INTEGER): Viewer;
- (*create and open at X, Y new menu viewer containing frames Menu and Main*)
- END MenuViewers.
- Remark:
- Messages to menu viewers not affexting size and position are passed on to their subframes. The ancestor
- viewer is made available to the subframe handlers via the variable Ancestor. MenuViewers also creates new
- messages of type ModifyMsg requesting subframes to change size or vertical position (or both). dY
- represents a vertical translation vector, and Y and H specify the new position and height respectively.
- --------------------------------------------------------------------------
- The Text System
- DEFINITION Fonts; (*font loader*)
- IMPORT Display;
- TYPE
- Name = ARRAY 32 OF CHAR;
- Font = POINTER TO FontDesc;
- FontDesc = RECORD
- name: Name; (*file name*)
- height, minX, maxX, minY, maxY: INTEGER; (*characteristic data*)
- raster: Display.Font (*raster data*)
- END;
- (*height = minimum distance between text lines,
- minX, maxX, minY, maxY are minima and maxima of X and Y,
- if all character boxes of the font are placed at the origin 0, 0*)
- VAR Default: Font; (*the default font*)
- PROCEDURE This (name: ARRAY OF CHAR): Font;
- (*font with name given*)
- END Fonts.
- --------------------------------------------------------------------------
- DEFINITION Texts; (*text manager*)
- IMPORT Files, Fonts;
- CONST
- (*symbol classes, see def. of type Scanner*)
- Inval = 0; (*invalid symbol*)
- Name = 1; (*name s (length len)*)
- String = 2; (*literal string s (length len)*)
- Int = 3; (*integer i (decimal or hexadecimal)*)
- Real = 4; (*real number x*)
- LongReal = 5; (*long real number y*)
- Char = 6; (*special character c*)
- replace = 0; insert = 1; delete = 2; (*op-codes*)
- TYPE
- Text = POINTER TO TextDesc;
- Notifier = PROCEDURE (T: Text; op: INTEGER; beg, end: LONGINT);
- TextDesc = RECORD
- len: LONGINT; (*text length*)
- notify: Notifier (*of editing operations*)
- END;
- Reader = RECORD
- (Files.Rider)
- eot: BOOLEAN;
- fnt: Fonts.Font; (*font of current character*)
- col: SHORTINT; (*color of current character*)
- voff: SHORTINT (*vertical offset*)
- END;
- Scanner = RECORD
- (Reader)
- nextCh: CHAR;
- line: INTEGER;
- class: INTEGER;
- i: LONGINT;
- x: REAL;
- y: LONGREAL;
- c: CHAR;
- len: SHORTINT;
- s: ARRAY 32 OF CHAR
- END;
- (*used to convert a text into a stream of symbols.
- Symbol classes are defined under CONST*)
- Buffer = POINTER TO BufDesc;
- BufDesc = RECORD
- len: LONGINT (*buffer length*)
- END;
- (*used to write a stream of textual data in a buffer*)
- (*used to store a stretch of a text*)
- Writer = RECORD
- (Files.Rider)
- buf: Buffer; (*associated buffer*)
- fnt: Fonts.Font; (*current font*)
- col: SHORTINT; (*color of current character*)
- voff: SHORTINT (*vertical offset*)
- END;
- PROCEDURE Load (T: Text; f: Files.File; pos: LONGINT; VAR len: LONGINT);
- (*load text block from file f at position pos to text T*)
- PROCEDURE Open (T: Text; name: ARRAY OF CHAR);
- (*open text T from disk file specified by name; open new text if name = ""*)
- PROCEDURE OpenBuf (B: Buffer);
- (*open new text buffer B*)
- PROCEDURE OpenReader (VAR R: Reader; T: Text; pos: LONGINT);
- (*open text reader R and set it up at position pos in text T*)
- PROCEDURE Read (VAR R: Reader; VAR ch: CHAR);
- (*read next character in ch*)
- PROCEDURE Pos (VAR R: Reader): LONGINT;
- (*return reader's position within its text*)
- PROCEDURE Store (T: Text; f: Files.File; pos: LONGINT; VAR len: LONGINT);
- (*store text T on disk file f at position pos*)
- PROCEDURE Save (T: Text; beg, end: LONGINT; B: Buffer);
- (*append stretch [beg, end[ of text T to buffer B*)
- PROCEDURE Copy (SB, DB: Buffer);
- (*append copy of source buffer SB to destination buffer DB*)
- PROCEDURE ChangeLooks (T: Text; beg, end: LONGINT; sel: SET; fnt: Fonts.Font; col, voff: SHORTINT);
- (*change character attributes within stretch [beg, end[ of text T. sel selects attributes to be changed.
- 0, 1, 2 IN sel = fnt, col, voff selected*)
- PROCEDURE Insert (T: Text; pos: LONGINT; B: Buffer);
- (*insert buffer B in text T at position pos*)
- PROCEDURE Append (T: Text; B: Buffer);
- (*append buffer B to text T*)
- PROCEDURE Delete (T: Text; beg, end: LONGINT);
- (*delete stretch [beg, end[ of text T*)
- PROCEDURE Recall (VAR B: Buffer);
- (*recall previously deleted text*)
- PROCEDURE OpenScanner (VAR S: Scanner; T: Text; pos: LONGINT);
- (*open text scanner S and set it up at position pos in text T*)
- PROCEDURE Scan (VAR S: Scanner);
- (*read next symbol*)
- PROCEDURE OpenWriter (VAR W: Writer);
- (*open new writer W*)
- PROCEDURE SetFont (VAR W: Writer; fnt: Fonts.Font);
- (*set writer W to font fnt*)
- PROCEDURE SetColor (VAR W: Writer; col: SHORTINT);
- (*set writer W to color col*)
- PROCEDURE SetOffset (VAR W: Writer; voff: SHORTINT);
- (*set writer W to vertical offset voff*)
- PROCEDURE Write (VAR W: Writer; ch: CHAR);
- (*write character ch to W's buffer*)
- PROCEDURE WriteLn (VAR W: Writer);
- (*write end-of-line to W's buffer*)
- PROCEDURE WriteInt (VAR W: Writer; x, n: LONGINT);
- (*write integer x to W's buffer. Right adjust to n positions*)
- PROCEDURE WriteHex (VAR W: Writer; x: LONGINT);
- (*write integer x to W's buffer in hexadecimal form.
- PROCEDURE WriteString (VAR W: Writer; s: ARRAY OF CHAR);
- (*write string s to W's buffer*)
- PROCEDURE WriteReal (VAR W: Writer; x: REAL; n: INTEGER);
- (*write real number x to W's buffer. Use n positions*)
- PROCEDURE WriteRealFix (VAR W: Writer; x: REAL; n, k: INTEGER);
- (*write real number x to W's buffer in fixed-point form,
- using k positions for decimal fractions and n positions in total*)
- PROCEDURE WriteRealHex (VAR W: Writer; x: REAL);
- (*write real number x to W's buffer in hexadecimal form*)
- PROCEDURE WriteLongReal (VAR W: Writer; x: LONGREAL; n: INTEGER);
- (*write long real number x to W's buffer. Use n positions*)
- PROCEDURE WriteLongRealHex (VAR W: Writer; x: LONGREAL);
- (*write long real number x to W's buffer in hexadecimal form*)
- END Texts.
- Remark:
- Open does not create a text object nor does it install a notifier procedure. Both actions are left to the calling
- modules. Typically, a calling module first creates a text object (or an extension of it) by using NEW, and then
- installs a notifier procedure. The main purpose of notifier procedures is requesting the display to
- re-establish consistency after a change in a text has occurred.
- --------------------------------------------------------------------------
- DEFINITION TextFrames; (*text display*)
- IMPORT Display, Texts;
- TYPE
- Location = RECORD
- org, pos: LONGINT; (*line origin, position*)
- dx, x, y: INTEGER (*width and position of located character*)
- END;
- Frame = POINTER TO FrameDesc;
- FrameDesc = RECORD
- (Display.FrameDesc)
- text: Texts.Text; (*displayed text*)
- org: LONGINT; (*position in text of first displayed character*)
- col: INTEGER; (*background color*)
- lsp, asr, dsr: INTEGER; (*line spacing, ascender, descender*)
- left, right, top, bot: INTEGER; (*margins*)
- markH: INTEGER; (*margin width, position of mark*)
- time: LONGINT; (*time of latest selection*)
- mark, car, sel: INTEGER; (*state of mark, caret, selection*)
- carloc: Location; (*caret location*)
- selbeg, selend: Location (*locations of begin and end of selection*)
- END;
- (*mark < 0: arrow mark
- mark = 0: no mark
- mark > 0: position mark
- car = 0: caret not set
- car > 0: caret set
- sel = 0: no selection active
- sel > 0: selection active*)
- UpdateMsg* = RECORD
- (Display.FrameMsg)
- id: INTEGER;
- text: Texts.Text;
- beg, end: LONGINT
- END;
- VAR menuH, barW, left, right, top, bot, asr, dsr, lsp: INTEGER; (*standard sizes*)
- PROCEDURE Restore (F: Frame);
- (restore frame F*)
- PROCEDURE Suspend(F: Frame);
- (*suspend frame F*)
- PROCEDURE Extend (F: Frame; newY: INTEGER);
- (*extend frame F to bottom newY*)
- PROCEDURE Reduce (F: Frame; newY: INTEGER);
- (*reduce frame F to bottom newY*)
- PROCEDURE Mark (F: Frame; mark: INTEGER);
- (*mark frame F as specified by mark*)
- PROCEDURE Show (F: Frame; pos: LONGINT);
- (*show text part containing position pos in frame F*)
- PROCEDURE Pos (F: Frame; X, Y: INTEGER): LONGINT;
- (*convert coordinates X, Y to text position*)
- PROCEDURE SetCaret (F: Frame; pos: LONGINT);
- (*set caret in frame F at position pos*)
- PROCEDURE TrackCaret (F: Frame; X, Y: INTEGER; VAR keysum: SET);
- (*track caret in frame F, starting from X, Y, and return mouse-keys pressed*)
- PROCEDURE RemoveCaret (F: Frame);
- (*remove caret from frame F*)
- PROCEDURE SetSelection (F: Frame; beg, end: LONGINT);
- (*select text stretch [beg, end[ in F*)
- PROCEDURE TrackSelection (F: Frame; X, Y: INTEGER; VAR keysum: SET);
- (*track selection in frame F, starting from X, Y, and return mouse-keys pressed*)
- PROCEDURE RemoveSelection (F: Frame);
- (*remove selection from frame F*)
- PROCEDURE TrackLine (F: Frame; X, Y: INTEGER; VAR org: LONGINT; VAR keysum: SET);
- (*track text line in frame F, starting from X, Y, and return line-origin and mouse-keys pressed*)
- PROCEDURE TrackWord (F: Frame; X, Y: INTEGER; VAR pos: LONGINT; VAR keysums: SET);
- (*track text word in frame F, starting from X, Y,
- and return starting position and mouse-keys pressed*)
- PROCEDURE Replace (F: Frame; beg, end: LONGINT);
- (*text stretch [beg, end[ was replaced; update frame F*)
- PROCEDURE Insert (F: Frame; beg, end: LONGINT);
- (*text stretch [beg, end[ was inserted; update frame F*)
- PROCEDURE Delete (F: Frame; beg, end: LONGINT);
- (*text stretch [beg, end[ was deleted; update frame F*)
- (*---------------- message handling ----------------*)
- PROCEDURE NotifyDisplay (T: Texts.Text; op: INTEGER; beg, end: LONGINT);
- (*notify display manager of text status change*)
- PROCEDURE Call* (F: Frame; pos: LONGINT; new: BOOLEAN);
- (*call command specified at pos in frame F. new forces loading of newest version*)
- PROCEDURE Write* (F: Frame; ch: CHAR; fnt: Fonts.Font; col, voff: SHORTINT);
- (*write character ch with given attributes at caret position*)
- PROCEDURE Defocus* (F: Frame); (F: Frame; ch: CHAR; fnt: Fonts.Font; col, voff: SHORTINT);
- (*remove caret*)
- PROCEDURE Neutralize* (F: Frame);
- (*remove marks*)
- PROCEDURE Modify* (F: Frame; id, dY, Y, H: INTEGER);
- (*vertically translate and extend or reduce frame F. id indicates type (extension or reduction),
- dy is a translation vector, and Y, H specify new location and height respectively*)
- PROCEDURE Open* (
- F: Frame; H: Display.Handler; T: Texts.Text; org: LONGINT;
- col, left, right, top, bot, asr, dsr, lsp: INTEGER);
- (*open new text frame F displaying text T starting from position org, with background color col,
- margins left, right, top, bot, and line geometry asr, dsr, lsp = ascender, descender line spacing.
- Install notifier H*)
- PROCEDURE Copy* (F: Frame; VAR F1: Frame);
- (*generate copy F1 of frame F. Initialize to empty frame*)
- PROCEDURE CopyOver* (F: Frame; text: Texts.Text; beg, end: LONGINT);
- (*copy over text stretch [beg, end[ to caret position in frame F*)
- PROCEDURE GetSelection* (F: Frame; VAR text: Texts.Text; VAR beg, end, time: LONGINT);
- (*get current text selection in frame F (if any)*)
- PROCEDURE Update* (F: Frame; VAR M: UpdateMsg);
- (*update display after editing operation*)
- PROCEDURE Edit* (F: Frame; X, Y: INTEGER; Keys: SET);
- (*track mouse and interpret editing commands*)
- PROCEDURE Handle* (F: Display.Frame; VAR M: Display.FrameMsg);
- (*standard handler for text frames*)
- PROCEDURE Text* (name: ARRAY OF CHAR): Texts.Text;
- (*create new displayed text from named file. Empty file name means empty text*)
- PROCEDURE NewMenu* (name, commands: ARRAY OF CHAR): Frame;
- (*create new menu frame containing listed commands*)
- PROCEDURE NewText* (text: Texts.Text; pos: LONGINT): Frame;
- (*create new standard text frame*)
- END TextFrames.
- --------------------------------------------------------------------------
- The Oberon Core
- DEFINITION Math; (*math library for reals*)
- CONST pi = 3.14159265; e = 2.71828182;
- PROCEDURE sqrt(x: REAL): REAL;
- PROCEDURE exp(x: REAL): REAL;
- PROCEDURE ln(x: REAL): REAL;
- PROCEDURE sin(x: REAL): REAL;
- PROCEDURE cos(x: REAL): REAL;
- PROCEDURE arctan(x: REAL): REAL;
- END Math.
- --------------------------------------------------------------------------
- DEFINITION MathL; (*math library for longreals*)
- CONST pi = 3.141592653589793D0;
- e = 2.718281828459045D0;
- PROCEDURE sqrt(x: LONGREAL): LONGREAL;
- PROCEDURE exp(x: LONGREAL): LONGREAL;
- PROCEDURE ln(x: LONGREAL): LONGREAL;
- PROCEDURE sin(x: LONGREAL): LONGREAL;
- PROCEDURE cos(x: LONGREAL): LONGREAL;
- PROCEDURE arctan(x: LONGREAL): LONGREAL;
- END MathL.
- --------------------------------------------------------------------------
- DEFINITION Files; (*file manager*)
- TYPE Handle = RECORD END ;
- File = POINTER TO Handle;
- (*A file is a sequence of bytes, accessed via (a pointer to) a handle. Files are stored on disk and
- may be referenced through a name entered in the file directory*)
- Rider = RECORD
- res: INTEGER;
- eof: BOOLEAN;
- file: File
- END ;
- (*Elements of files are accessed through a rider, which has a position that is advanced when
- reading or writing data. The position is an integer between 0 and the length of the file to which
- the rider is attached. The fields eof and res serve as result parameters of file procedures.*)
- PROCEDURE Old(name: ARRAY OF CHAR): File;
- (*the file with the given name. NIL if the name is not in the directory*)
- PROCEDURE New(name: ARRAY OF CHAR): File;
- (*a new file with given name*)
- PROCEDURE Register(f: File);
- (*Close file f and register it under its name in the directory.
- If the name exists already, the corresponding old file is unregistered*)
- PROCEDURE Close(f: File);
- PROCEDURE Purge(f: File);
- PROCEDURE Length(f: File): LONGINT; (*the number of bytes in the file*)
- PROCEDURE Set(VAR r: Rider; f: File; pos: LONGINT);
- (*Associate rider r with file f at position pos. r.eof := FALSE*)
- PROCEDURE Read(VAR r: Rider; VAR x: BYTE);
- (*read byte and advance rider by one position. If at end, r.eof := TRUE and x := 0X*)
- PROCEDURE ReadBytes(VAR r: Rider; VAR x: ARRAY OF BYTE; n: INTEGER);
- (*read n bytes and advance rider by n positions.
- If at end, r.eof := TRUE and r.res := no. of bytes requested but not read.*)
- PROCEDURE Write(VAR r: Rider; x: BYTE);
- (*write byte and advance rider by one position*)
- PROCEDURE WriteBytes(VAR r: Rider; VAR x: ARRAY OF BYTE; n: INTEGER);
- (*write n bytes and advance rider by n positions*)
- PROCEDURE Pos(VAR r: Rider): LONGINT;
- PROCEDURE Base(VAR r: Rider): File;
- PROCEDURE Rename(old, new: ARRAY OF CHAR; VAR res: INTEGER);
- (*res = 0: renamed; res = 1: new name existed already and now denotes the renamed file;
- res = 2: old name not in directory; res = 3: name is illegal; res = 4: name is too long *)
- PROCEDURE Delete(name: ARRAY OF CHAR; VAR res: INTEGER);
- (*res = 0: deleted; res = 2: name not in directory;
- res = 3: name is illegal; res = 4: name is too long *)
- END Files.
- --------------------------------------------------------------------------
- DEFINITION Diskette; (*diskette manager*)
- TYPE EntryHandler* = PROCEDURE (name: ARRAY OF CHAR; date, time: INTEGER; size: LONGINT);
- VAR res: INTEGER; (*result of file-oriented operation, error occurred = (res # 0)*)
- err: SHORTINT; sect: LONGINT; busy: BOOLEAN; (*state of device driver*)
- (*device driver*)
- PROCEDURE Reset;
- PROCEDURE GetSector (sec: INTEGER; VAR buf: ARRAY OF BYTE; off: INTEGER);
- PROCEDURE PutSector (sec: INTEGER; VAR buf: ARRAY OF BYTE; off: INTEGER);
- PROCEDURE Format;
- (*directory handler*)
- PROCEDURE InitDir (format: CHAR); (*format for future extension*)
- PROCEDURE ReadDir;
- PROCEDURE WriteDir;
- PROCEDURE GetData (VAR date, time, nofFiles, nofClusters: INTEGER); (*get volume data*)
- PROCEDURE Enumerate (proc: EntryHandler);
- (*file handler*)
- PROCEDURE ReadAll;
- PROCEDURE ReadFile (name: ARRAY OF CHAR);
- PROCEDURE WriteFile (name: ARRAY OF CHAR);
- PROCEDURE DeleteFile (name: ARRAY OF CHAR);
- END Diskette.
- --------------------------------------------------------------------------
- DEFINITION Input; (*keyboard and mouse driver*)
- PROCEDURE Available(): INTEGER;
- (*the number of characters available from the keyboard*)
- PROCEDURE Read (VAR ch: CHAR);
- (*next character from keyboard*)
- PROCEDURE Mouse (VAR keys: SET; VAR x, y: INTEGER);
- (*current coordinates and key setting of mouse.
- 0 IN keys = right key pressed
- 1 IN keys = middle key pressed
- 2 IN keys = left key pressed*)
- PROCEDURE SetMouseLimits (w, h: INTEGER);
- (* define width and height of rectangle in which mouse moves*)
- PROCEDURE Time(): LONGINT;
- (* current system time in units of 1/300 sec*)
- END Input.
- --------------------------------------------------------------------------
- DEFINITION SCC; (*SCC driver*)
- (*Serial Communications Controller driver module (Zilog Z8530)
- Data are transmitted in blocks. Each block contains two parts: header and data *)
- TYPE Header =
- RECORD valid: BOOLEAN; dadr, sadr, typ: SHORTINT;
- len: INTEGER; (*of data following header*)
- destLink, srcLink: INTEGER (*link numbers*)
- END ;
- (*dadr is the receiver's machine number, len is the length (number of bytes) of
- the data part. typ, destLink, and srcLink are not interpreted by SCC*)
- PROCEDURE Start(filter: BOOLEAN);
- (*initialise the SCC*)
- PROCEDURE Send(VAR head, buf: ARRAY OF BYTE);
- (*send buf[0] ... buf[head.len-1] to head.adr*)
- PROCEDURE Available(): INTEGER;
- (*number of bytes available from receiver buffer. Buffer contains stream of
- received bytes, including headers and data parts*)
- PROCEDURE ReceiveHead(VAR head: ARRAY OF BYTE);
- (*read a header from the receiver buffer*)
- PROCEDURE Receive(VAR x: BYTE);
- (*read a byte from the receiver buffer*)
- PROCEDURE Skip(m: INTEGER);
- (*skip m bytes in the receiver buffer*)
- PROCEDURE Stop; (*turn SCC off*)
- END SCC.
- --------------------------------------------------------------------------
- DEFINITION V24; (*V24 driver*)
- (*interrupt-driven UART channel B*)
- PROCEDURE Start(CSR, MR2: CHAR);
- (* Clock Select Register:
- 66X: 1200 bps
- 88X: 2400 bps
- 0BBX: 9600 bps
- Mode Register 2:
- 7X: 1 stop bit
- 0FX: 2 stop bits *)
- PROCEDURE SetOP(s: SET); (*output port*)
- PROCEDURE ClearOP(s: SET);
- (* 0: DTR, 1: RTS *)
- PROCEDURE IP(n: INTEGER): BOOLEAN; (*input port*)
- PROCEDURE SR(n: INTEGER): BOOLEAN;
- (*Status Register. 0: Rx rdy, 2: Tx rdy, 4: overrun*)
- PROCEDURE Available(): INTEGER;
- PROCEDURE Receive(VAR x: BYTE);
- PROCEDURE Send(x: BYTE);
- PROCEDURE Break;
- PROCEDURE Stop;
- END V24.
- --------------------------------------------------------------------------
- DEFINITION Printer; (*printer interface*)
- VAR res: INTEGER; (*result*)
- PROCEDURE Open(VAR name, user: ARRAY OF CHAR; password: LONGINT);
- (*res = 0: opened, 1: no printer, 2: no link, 3: bad response, 4: no permission*)
- PROCEDURE Font (fno: SHORTINT; VAR name: ARRAY OF CHAR); (*install font*)
- PROCEDURE String (x, y: INTEGER; VAR s: ARRAY OF CHAR; fno: SHORTINT); (*place string*)
- PROCEDURE ContString (VAR s: ARRAY OF CHAR; fno: SHORTINT); (*place continuation string*)
- PROCEDURE Line (x, y, w, h: INTEGER); (*place horizontal or vertical line*)
- PROCEDURE XLine (x, y, dx, dy: INTEGER); (*place line of general direction*)
- PROCEDURE Circle (x, y, a, b: INTEGER); (*place circle or ellipsis*)
- PROCEDURE Shade (x, y, w, h, col: INTEGER); (*shade area*)
- PROCEDURE Picture (x, y, w, h, mode: INTEGER; adr: LONGINT); (*place picture*)
- PROCEDURE Page(nofcopies: INTEGER); (*print current page*)
- PROCEDURE Close; (*close connection*)
- END Printer.
- --------------------------------------------------------------------------
- DEFINITION Oberon; (*system manager*)
- IMPORT Display, Viewers, Texts;
- CONST
- consume = 0; track = 1; (*ids for input messages*)
- defocus = 0; neutralize = 1; mark = 2; (*ids for control messages*)
- TYPE
- Painter = PROCEDURE (x, y: INTEGER);
- Marker = RECORD Fade, Draw: Painter END;
- Cursor = RECORD
- on: BOOLEAN; m: Marker; X, Y: INTEGER
- END;
- ParList = POINTER TO ParRec;
- ParRec = RECORD
- vwr: Viewers.Viewer; (*caller's viewer*)
- frame: Display.Frame; (*caller's sub-frame*)
- text: Texts.Text; (*parameter list*)
- pos: LONGINT (*starting position of parameter list*)
- END;
- InputMsg = RECORD
- (Display.FrameMsg)
- id: INTEGER; (*message id*)
- modes, keys: SET; (*current modes and mouse keys*)
- X, Y: INTEGER; (*current location of the mouse*)
- ch: CHAR (*current char*)
- END;
- ControlMsg = RECORD
- (Display.FrameMsg)
- id: INTEGER; (*message id*)
- X, Y: INTEGER (*current location of the mous*)
- END;
- SelectionMsg = RECORD
- (Display.FrameMsg)
- time: LONGINT;
- text: Texts.Text;
- beg, end: LONGINT
- END;
- CopyOverMsg* = RECORD
- (Display.FrameMsg)
- text*: Texts.Text;
- beg*, end*: LONGINT
- END;
- CopyMsg* = RECORD
- (Display.FrameMsg)
- F*: Display.Frame
- END;
- Task = POINTER TO TaskDesc; (*installable task*)
- Handler = PROCEDURE;
- TaskDesc = RECORD
- safe: BOOLEAN; (*safe tasks are not removed after trap*)
- handle: Handler
- END;
- VAR
- (*configuration*)
- FocusViewer: Viewers.Viewer; (*current focus viewer*)
- Log: Texts.Text; (*system log text*)
- Par: ParList; (*actual parameters for next command*)
- User: ARRAY 8 OF CHAR; Password: LONGINT; (*current user*)
- CurFnt, CurCol:, CurOff SHORTINT; (*current font, color, vertical offset*)
- Arrow, Star: Marker;
- Mouse, Pointer: Cursor;
- (*user identification*)
- PROCEDURE SetUser (VAR user, password: ARRAY OF CHAR);
- (*clocks*)
- PROCEDURE GetClock (VAR t, d: LONGINT);
- PROCEDURE SetClock (t, d: LONGINT);
- PROCEDURE Time (): LONGINT; (*in units of 1/300 sec*)
- (*cursor handling*)
- PROCEDURE OpenCursor (VAR c: Cursor);
- PROCEDURE FadeCursor (VAR c: Cursor);
- PROCEDURE DrawCursor (VAR c: Cursor; VAR m: Marker; X, Y: INTEGER);
- (*display management*)
- PROCEDURE OpenDisplay (UW, SW, H: INTEGER);
- (*initialize new display with user track width UW, system track width SW, and height H*)
- PROCEDURE DisplayWidth (X: INTEGER): INTEGER;
- (*get width of display at X*)
- PROCEDURE DisplayHeight (X: INTEGER): INTEGER;
- (*get height of display at X*)
- PROCEDURE OpenTrack (X, W: INTEGER);
- (*open a new track of width W at X*)
- PROCEDURE UserTrack (X: INTEGER): INTEGER;
- (*get left margin of user track at X*)
- PROCEDURE SystemTrack (X: INTEGER): INTEGER;
- (*get left margin of system track at X*)
- PROCEDURE AllocateUserViewer (DX: INTEGER; VAR X, Y: INTEGER);
- (*allocate new user viewer within display at DX*)
- PROCEDURE AllocateSystemViewer (DX: INTEGER; VAR X, Y: INTEGER);
- (*allocate new system viewer within display at DX*)
- PROCEDURE PassFocus (V: Viewers.Viewer);
- (*pass focus to viewer V*)
- PROCEDURE RemoveMarks (X, Y, W, H: INTEGER);
- (*remove marks within given rectangle*)
- PROCEDURE MarkedViewer (): Viewers.Viewer;
- (*returns viewer marked by star-shaped pointer*)
- (*command interpretation*)
- PROCEDURE ShowMenu (VAR cmd: INTEGER; X, Y: INTEGER; menu: ARRAY OF CHAR);
- (* menu = {command "|"} command.
- Six commands allowed, 6 > cmd >= -1.
- cmd = 5: first command selected
- cmd = 0: last command selected
- cmd = -1: no selection *)
- PROCEDURE Call (VAR name: ARRAY OF CHAR; par: ParList; new: BOOLEAN; VAR res: INTEGER);
- (*call command name and pass parameter list par. Option new requests loading of module.
- Done = (res = 0)*)
- PROCEDURE GetSelection (VAR text: Texts.Text; VAR beg, end, time: LONGINT);
- (*get most recent text selection. Text selection exists = (time >= 0)*)
- PROCEDURE Install (T: Task);
- (*install new task T*)
- PROCEDURE Remove (T: Task);
- (*remove installed task T*)
- PROCEDURE Collect;
- (*demand garbage collector*)
- PROCEDURE SetFont* (fnt: Fonts.Font);
- (*set current font*)
- PROCEDURE SetColor* (col: SHORTINT);
- (*set current color*)
- PROCEDURE SetOffset* (voff: SHORTINT);
- (*set current vertical offset*)
- END Oberon.
- Remark;
- Installed tasks are considered to be background activities. They are activated by the central loop when no
- input events have been detected. For example, the garbage collector is implemented as an installed task.
- Notice that installed tasks may be invalidated after their host module has been unloaded (or replaced).
- Unsafe tasks are automatically removed after a system trap in order to avoid an infinite repetition of the
- same error.
- --------------------------------------------------------------------------
- Tutorial Examples
- Write time stamp to system log
- PROCEDURE TimeStamp;
- BEGIN
- Texts.WriteString(W, "TimeStamp "); Texts.WriteInt(W, Oberon.Time(), 1); Texts.WriteLn(W);
- Texts.Append(Oberon.Log, W.buf)
- END TimeStamp;
- where
- VAR W: Texts.Writer;
- is globally defined initialized by Texts.OpenWriter(W).
- Remarks:
- 1. Normally, one (global) writer per module is sufficient.
- 2. If you desire a specific part of the output text to appear in a new font, for example in italics variant
- Syntax10i.Scn.Fnt, call Texts.SetFont(W,Fonts.This("Syntax10i.Scn.Fnt")) before writing this part and
- Texts.SetFont(W,Fonts.Default) before continuing to write ordinary text.
- Process selected text
- PROCEDURE CountWords;
- VAR T: Texts.Text; R: Texts.Reader;
- beg, end, pos, time: LONGINT; words: INTEGER; ch: CHAR;
- BEGIN words := 0;
- Oberon.GetSelection(T, beg, end, time); (*get most recent selection*)
- IF time >= 0 THEN (*if it exists*)
- Texts.OpenReader(R, T, beg); pos := beg; (*setup reader and initialize pos*)
- Texts.Read(R, ch); INC(pos); (*read next character*)
- IF (pos # end) & (ch > " ") THEN
- REPEAT Texts.Read(R, ch); INC(pos) UNTIL (pos = end) OR (ch <= " ");
- INC(words)
- END;
- WHILE pos # end DO
- (*(pos # end) & (ch <= " ")*)
- REPEAT Texts.Read(R, ch); INC(pos) UNTIL (pos = end) OR (ch > " ");
- IF pos # end THEN
- REPEAT Texts.Read(R, ch); INC(pos) UNTIL (pos = end) OR (ch <= " ");
- INC(words)
- END
- END
- END;
- Texts.WriteString(W, "WordCount = "); Texts.WriteInt(W, words, 1); Texts.WriteLn(W);
- Texts.Append(Oberon.Log, W.buf) (*append to system log*)
- END CountWords;
- where again
- VAR W: Texts.Writer;
- is globally defined and initialized by Texts.OpenWriter(W).
- Open a viewer in system track, generate, and display text data
- PROCEDURE Directory;
- VAR Menu, Main: TextFrames.Frame; T: Texts.Text; V: Viewers.Viewer; X, Y: INTEGER;
- BEGIN
- T := TextFrames.Text(""); (*generate new (and empty) text to be displayed in a frame*)
- Menu := TextFrames.NewMenu("Directory", StandardMenu); (*generate standard menu frame*)
- Main := TextFrames.NewText(T, 0); (*generate standard text frame*)
- Oberon.AllocateSystemViewer(Oberon.Par.vwr.X, X, Y);
- V := MenuViewers.New(Menu, Main, TextFrames.menuH, X, Y); (*open standard menu viewer*)
- TextFrames.Mark(Main, -1); (*setup vertical arrow mark*)
- Diskette.Enumerate(Lister); (*pass over Lister-procedure to enumerator*)
- Texts.Append(T, W.buf); (*append writer to T and display written text*)
- TextFrames.Mark(Main, 1) (*restore position mark*)
- END Directory;
- where
- CONST StandardMenu = "System.Close System.Copy System.Grow Edit.Search Edit.Store";
- VAR T: Texts.Text; W: Texts.Writer;
- are globally defined, W is globally initialized by Texts.OpenWriter(W), and Lister is an (upcalled) procedure
- displaying directory entries:
- PROCEDURE* Lister (name: ARRAY OF CHAR; date, time: INTEGER; size: LONGINT);
- BEGIN
- Texts.WriteString(W, name);
- Texts.Write(W, " "); Texts.WriteInt(W, size, 1);
- Texts.Write(W, " "); Texts.WriteDate(W, time, date);
- Texts.WriteLn(W)
- END Lister;
- Remarks:
- 1. The above program generates its whole output text before displaying it. Alternatively, if you move the
- statement Texts.Append(T, W.buf) into the Lister-procedure, every generated directory entry is displayed
- immediately.
- 2. Oberon.AllocateSystemViewer(Oberon.Par.vwr.X, X, Y) is a standard proposal for the placing of a new
- system viewer within the track from which the command was called. Of course, individual algorithms are
- possible as well. For example, if the new viewer is desired to cover the bottom most viewer, except if the
- pointer overrides this, the algorithm is
- PROCEDURE AllocateSystemViewer (DX: INTEGER; VAR X, Y: INTEGER);
- VAR bot: Viewers.Viewer;
- BEGIN
- IF Oberon.Pointer.on THEN X := Oberon.Pointer.X; Y := Oberon.Pointer.Y
- ELSE bot := Viewers.This(Oberon.SystemTrack(DX), 0); X := bot.X; Y := bot.H - Viewers.minH
- END
- END AllocateSystemViewer;
- 3. TextFrames.NewText generates a standard text frame. The following statement sequence produce a text
- frame with an individual handler and a customized geometry.
- NEW(F); Open(F, Handle, text, pos, col, left, right, top, bot, asr, dsr, lsp);
- where F is of type TextFrames.Frame.
- Open a viewer in user track and display existing text
- PROCEDURE OpenText;
- VAR par: Oberon.ParList; Text: TextFrames.Frame; S: Texts.Scanner;
- V: Viewers.Viewer; X, Y: INTEGER;
- BEGIN
- par := Oberon.Par; (*access parameters*)
- Text := par.frame(TextFrames.Frame); (*calling frame*)
- TextFrames.Mark(Text, -1); (*arrow mark*)
- Texts.OpenScanner(S, par.text, par.pos); (*open scanner at position of parameter list*)
- Texts.Scan(S); (*get symbol*)
- IF S.class = Texts.Name THEN
- Oberon.AllocateUserViewer(par.vwr.X, X, Y);
- V := MenuViewers.New(
- TextFrames.NewMenu(S.s, StandardMenu);
- TextFrames.NewText(TextFrames.Text(S.s), 0);
- TextFrames.menuH, X, Y);
- END;
- TextFrames.Mark(Text, 1) (*restore position mark*)
- END OpenText;
- Remark:
- Oberon.AllocateUserViewer(par.vwr.X, X, Y) is a standard proposal for the placing of a new viewer in the
- caller's user track. Again, individual algorithms are possible as well.
- Grow viewer
- PROCEDURE Grow;
- VAR V, newV: Viewers.Viewer; M: Oberon.CopyMsg; N: Viewers.ViewerMsg; DH: INTEGER;
- BEGIN
- V := Oberon.Par.vwr; (*get originator viewer*)
- DH := Oberon.DisplayHeight(V.X); (*get height of this track*)
- IF V.H < Oberon.DisplayHeight(V.X) THEN (*if viewer is small*)
- Oberon.OpenTrack(V.X, V.W); (*open overlaying track*)
- V.handle(V, M); newV := M.F(Viewers.Viewer); (*get a copy of the viewer*)
- Viewers.Open(newV, V.X, DH); (*open new big viewer*)
- N.id := Viewers.restore; newV.handle(newV, N) (*ask new viewer to draw itself*)
- END
- END Grow;
- Remark:
- The Grow command is generic in the sense that it can handle viewer instances of any (current or future)
- class. Typically (and unavoidably) generic commands use message passing instead of ordinary procedure
- calls. This object-oriented style will be explained in more detail in the next chapter. Also notice that actually a
- copy of the original viewer is opened in the new track. When this track is being closed later, the original
- viewer will reappear.
- Process viewer text or sequence of texts, depending on context
- PROCEDURE ProcessText;
- VAR par: Oberon.ParList; Main: TextFrames.Frame; S: Texts.Scanner; T: Texts.Text;
- BEGIN
- par := Oberon.Par; (*access parameters*)
- IF par.frame = par.vwr.dsc THEN (*command in menu frame*)
- IF par.vwr.dsc.next IS TextFrames.Frame THEN
- Main := par.vwr.dsc.next(TextFrames.Frame); (*main text frame*)
- TextFrames.Mark(Main, -1) (*set arrow mark*)
- Process(Main.text); (*process displayed text*)
- TextFrames.Mark(Main, 1) (*restore position mark*)
- END
- ELSE (*command in main text frame*)
- Main := par.frame(TextFrames.Frame);
- TextFrames.Mark(Main, -1) (*set arrow mark*)
- Texts.OpenScanner(S, par.text, par.pos); (*open scanner at position of parameter list*)
- Texts.Scan(S); (*get first symbol*)
- WHILE S.class = Texts.Name DO
- Texts.Open(T, S.s); (*open text from file*)
- Process(T); (*process this text*)
- Texts.Scan(S) (*get next symbol*)
- END;
- TextFrames.Mark(Main, 1) (*restore position mark*)
- END
- END ProcessText;
- Delete selected part of text in marked viewer
- PROCEDURE Delete;
- VAR Main: TextFrames.Frame; V: Viewers.Viewer;
- BEGIN
- V := Oberon.MarkedViewer(); (*get marked viewer*)
- Main := V.dsc.next(TextFrames.Frame); (*main text frame of marked viewer*)
- IF Main.sel > 0 THEN (*if there exists a selection*)
- Texts.Delete(Main.text, Main.selbeg.pos, Main.selend.pos) (*delete text*)
- END
- END Delete;
- Copy most recently selected text part to caret's position
- PROCEDURE CopyText;
- VAR Main: TextFrames.Frame; buf: Texts.Buffer; V: Viewers.Viewer; time: LONGINT;
- BEGIN
- Oberon.GetSelection(T, beg, end, time); (*get most recent selection*)
- IF time >= 0 THEN (*if it exists*)
- Texts.OpenBuffer(buf);
- Texts.Save(T, beg, end, buf); (*save text in buffer*)
- V := Oberon.FocusViewer; (*get focus viewer*)
- IF (V.dsc # NIL) & (V.dsc.next IS TextFrames.Frame) THEN (*if text viewer*)
- Main := V.dsc.next(TextFrames.Frame); (*main text frame*)
- IF Main.car > 0 THEN (*if caret set*)
- Texts.Insert(Main.text, Main.carloc.pos, buf) (*insert text at caret's position*)
- END
- END
- END
- END CopyText;
- Copy font from visibly marked position to text selection
- PROCEDURE CopyFont;
- VAR F: TextFrames.Frame; T: Texts.Text; R: Texts.Reader; V: Viewers.Viewer;
- beg, end, time: LONGINT; X, Y: INTEGER; ch: CHAR;
- BEGIN
- Oberon.GetSelection(T, beg, end, time); (*get most recent selection*)
- IF (time >= 0) & Oberon.Pointer.on THEN (*if found and pointer visible*)
- X := Oberons.Pointer.X; Y := Oberon.Pointer.Y;
- V := Viewers.This(X, Y); (*marked viewer*)
- IF (V.dsc # NIL) & (V.dsc.next IS TextFrames.Frame) THEN
- F := V.dsc.next(TextFrames.Frame);
- IF (X >= F.X) & (X < F.X + F.W) & (Y >= F.Y) & (Y < F.Y + F.H) THEN
- Texts.OpenReader(R, F.text, TextFrames.Pos(F, X, Y)); (*position reader*)
- Texts.Read(R, ch); (*read marked char*)
- Texts.ChangeLooks(T, beg, end, {0}, R.fnt, 0, 0) (*change font alone*)
- END
- END
- END
- END CopyFont;
- Move caret to next character written in italics
- PROCEDURE SearchItalics;
- VAR Main: TextFrames.Frame; R: Texts.Reader; italic: Fonts.Font; V: Viewers.Viewer;
- pos: LONGINT; ch: CHAR;
- BEGIN
- italic := Fonts.This("Syntax10i.Scn.Fnt");
- V := Oberon.FocusViewer; (*get focus viewer*)
- IF (V.dsc # NIL) & (V.dsc.next IS TextFrames.Frame) THEN (*if text viewer*)
- Main := V.dsc.next(TextFrames.Frame); (*main text frame*)
- IF Main.car > 0 THEN (*if caret set*)
- Texts.OpenReader(R, Main.text, Main.carloc.pos); (*open reader at caret's position*)
- Texts.Read(R, ch);
- WHILE ~R.eot & (R.fnt # italic) DO Texts.Read(R, ch) END; (*read char stream*)
- IF ~R.eot THEN (*not end of text*)
- pos := Texts.Pos(R); (*reader's position*)
- TextFrames.RemoveSelection(Main); (*remove all marks*)
- TextFrames.RemoveCaret(Main);
- Oberon.RemoveMarks(Main.X, Main.Y, Main.W, Main.H);
- TextFrames.Show(Main, Max(0, pos - 200)); (*show text at pos*)
- TextFrames.SetCaret(Main, pos) (*set caret to new position*)
- END
- END
- END
- END SearchItalics;
- where Max is the maximum-function.
-